# coding=utf8
__author__ = 'lijian'
import threading
import serial
import logging
import struct
import time
import action
import manager
import datetime
from utils import byteUtil

from setting import RTU_SERIAL
from protocol import Packet
from protocol import PacketDecode


class RtuMonitor(threading.Thread):
    instance = None
    mutex = threading.Lock()

    @staticmethod
    def GetInstance():
        if (RtuMonitor.instance == None):
            RtuMonitor.mutex.acquire()
            if (RtuMonitor.instance == None):
                RtuMonitor.instance = RtuMonitor()
            RtuMonitor.mutex.release()

        return RtuMonitor.instance

    def __init__(self):
        super(RtuMonitor, self).__init__()

        self._lastTime = 0
        self._decoder = PacketDecode()

        self._mutex = threading.Lock()
        self._todayAction = None

    def reset(self):
        self._serial = serial.Serial(port=RTU_SERIAL['port'], baudrate=RTU_SERIAL['baudrate'],
                                     stopbits=RTU_SERIAL['stopbits'], parity=RTU_SERIAL['parity'],timeout=0.5)
        # self._serial.setTimeout(0.5)

    def run(self):
        manager.resetTodayAction()
        while True:
            action.queryDate()
            time.sleep(11)

    def send(self, packet):
        self._mutex.acquire()
        logging.debug("send  to rtu:%s" % packet.info())
        self.writeBytes(packet.pack())

        sendTime = time.time()
        timeout = False
        response = None
        while not timeout:
            raw = self.readBytes()
            if len(raw) > 0:
                remain = struct.unpack('B' * len(raw), raw)
                # logging.debug(byteUtil.formatBytes(remain))
                response = self._decoder.decode(remain)
                if response:
                    logging.debug("recv from rtu:%r" % response.info())
                    break

            now = time.time()
            if now - sendTime > 2:
                timeout = True
        self._mutex.release()
        return response

    def writeBytes(self, raw):
        self._serial.write(raw)

    def readBytes(self):
        raw = self._serial.read(1024)
        return raw


def startMonitor():
    th = RtuMonitor.GetInstance()
    th.setDaemon(True)
    th.start()